rockchip/rk3399: Add watchdog support in pmusram
authorDerek Basehore <[email protected]>
Mon, 23 Apr 2018 21:49:22 +0000 (14:49 -0700)
committerLin Huang <[email protected]>
Tue, 15 May 2018 08:31:19 +0000 (16:31 +0800)
To catch early hangs in resume, this sets up the watchdog before
anything else in the pmusram code (ignoring setting up the stack...).
This uses hard coded settings for the watchdog until the proper
watchdog restore later on in the firmware/kernel.

This also restores the old watchdog register values before the PLLs
are restored to make sure we don't temporarily switch over to a 1/3s
timeout on the watchdog when the pclk_wdt goes from 4MHz to 100MHz.

Change-Id: I8f7652089a88783271b17482117b4609330abe80
Signed-off-by: Derek Basehore <[email protected]>
plat/rockchip/rk3399/drivers/dram/suspend.c
plat/rockchip/rk3399/drivers/pmu/pmu.c
plat/rockchip/rk3399/drivers/secure/secure.c
plat/rockchip/rk3399/drivers/secure/secure.h
plat/rockchip/rk3399/drivers/soc/soc.c
plat/rockchip/rk3399/drivers/soc/soc.h

index 2a80bcb31b585b4818929845bb3f3021bbf68c60..dd97581db14d425be10e3df952f650bcdf262caa 100644 (file)
@@ -9,6 +9,8 @@
 #include <dram.h>
 #include <plat_private.h>
 #include <platform_def.h>
+#include <pmu.h>
+#include <pmu_bits.h>
 #include <pmu_regs.h>
 #include <rk3399_def.h>
 #include <secure.h>
@@ -656,6 +658,30 @@ __pmusramfunc static void pmusram_restore_pll(int pll_id, uint32_t *src)
                ;
 }
 
+__pmusramfunc static void pmusram_enable_watchdog(void)
+{
+       /* Make the watchdog use the first global reset. */
+       mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, 1 << 1);
+
+       /*
+        * This gives the system ~8 seconds before reset. The pclk for the
+        * watchdog is 4MHz on reset. The value of 0x9 in WDT_TORR means that
+        * the watchdog will wait for 0x1ffffff cycles before resetting.
+        */
+       mmio_write_32(WDT0_BASE + 4, 0x9);
+
+       /* Enable the watchdog */
+       mmio_setbits_32(WDT0_BASE, 0x1);
+
+       /* Magic reset the watchdog timer value for WDT_CRR. */
+       mmio_write_32(WDT0_BASE + 0xc, 0x76);
+
+       secure_watchdog_ungate();
+
+       /* The watchdog is in PD_ALIVE, so deidle it. */
+       mmio_clrbits_32(PMU_BASE + PMU_BUS_CLR, PMU_CLR_ALIVE);
+}
+
 void dmc_suspend(void)
 {
        struct rk3399_sdram_params *sdram_params = &sdram_config;
@@ -726,6 +752,9 @@ __pmusramfunc void dmc_resume(void)
        uint32_t channel_mask = 0;
        uint32_t channel;
 
+       pmusram_enable_watchdog();
+       pmu_sgrf_rst_hld_release();
+       restore_pmu_rsthold();
        sram_secure_timer_init();
 
        /*
index e136bbc9ea0d15ce8807dfa4c61bfa959a5172b8..04446d60629ed3ca71dc5fcbd88dc8083b56cc30 100644 (file)
@@ -1368,7 +1368,7 @@ int rockchip_soc_sys_pwr_dm_suspend(void)
        mmio_setbits_32(PMU_BASE + PMU_PWRDN_CON, BIT(PMU_SCU_B_PWRDWN_EN));
 
        wdt_register_save();
-       secure_watchdog_disable();
+       secure_watchdog_gate();
 
        /*
         * Disabling PLLs/PWM/DVFS is approaching WFI which is
@@ -1397,6 +1397,7 @@ int rockchip_soc_sys_pwr_dm_resume(void)
        plat_rockchip_restore_gpio();
        cru_register_restore();
        grf_register_restore();
+       wdt_register_restore();
        resume_uart();
        resume_apio();
        resume_gpio();
@@ -1406,10 +1407,8 @@ int rockchip_soc_sys_pwr_dm_resume(void)
        udelay(300);
        enable_dvfs_plls();
 
-       secure_watchdog_enable();
        secure_sgrf_init();
        secure_sgrf_ddr_rgn_init();
-       wdt_register_restore();
 
        /* restore clk_ddrc_bpll_src_en gate */
        mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3),
@@ -1460,12 +1459,10 @@ int rockchip_soc_sys_pwr_dm_resume(void)
                udelay(1);
        }
 
-       pmu_sgrf_rst_hld_release();
        pmu_scu_b_pwrup();
        pmu_power_domains_resume();
 
        restore_abpll();
-       restore_pmu_rsthold();
        clr_hw_idle(BIT(PMU_CLR_CENTER1) |
                                BIT(PMU_CLR_ALIVE) |
                                BIT(PMU_CLR_MSCH0) |
index 589d833c8f243dd2f08718942fd85d3260e80e22..1937b138084e3af3c6c413aa84f86a3db9e58504 100644 (file)
@@ -77,7 +77,7 @@ static void sgrf_ddr_rgn_config(uint32_t rgn,
                      BIT_WITH_WMSK(rgn));
 }
 
-void secure_watchdog_disable(void)
+void secure_watchdog_gate(void)
 {
        /**
         * Disable CA53 and CM0 wdt pclk
@@ -89,7 +89,7 @@ void secure_watchdog_disable(void)
                      BIT_WITH_WMSK(PCLK_WDT_CM0_GATE_SHIFT));
 }
 
-void secure_watchdog_enable(void)
+__pmusramfunc void secure_watchdog_ungate(void)
 {
        /**
         * Enable CA53 and CM0 wdt pclk
index 334805d0d13c420d72943d080ab96b884715be2b..8e80f2b9286e0cf4112577dee7d0e67a81ed0c82 100644 (file)
@@ -95,8 +95,8 @@
 #define PCLK_WDT_CM0_GATE_SHIFT                10
 
 /* export secure operating APIs */
-void secure_watchdog_disable(void);
-void secure_watchdog_enable(void);
+void secure_watchdog_gate(void);
+__pmusramfunc void secure_watchdog_ungate(void);
 void secure_timer_init(void);
 void secure_sgrf_init(void);
 void secure_sgrf_ddr_rgn_init(void);
index 7dd0b72e255b85a8d3401fb55f94efc9d8c50277..741adde66d5a8afc506bcd7a799f197b11f36c5e 100644 (file)
@@ -43,6 +43,9 @@ const unsigned char rockchip_power_domain_tree_desc[] = {
 /* sleep data for pll suspend */
 static struct deepsleep_data_s slp_data;
 
+/* sleep data that needs to be accessed from pmusram */
+__pmusramdata struct pmu_sleep_data pmu_slp_data;
+
 static void set_pll_slow_mode(uint32_t pll_id)
 {
        if (pll_id == PPLL_ID)
@@ -229,9 +232,9 @@ void set_pmu_rsthold(void)
        uint32_t rstnhold_cofig0;
        uint32_t rstnhold_cofig1;
 
-       slp_data.pmucru_rstnhold_con0 = mmio_read_32(PMUCRU_BASE +
+       pmu_slp_data.pmucru_rstnhold_con0 = mmio_read_32(PMUCRU_BASE +
                                            PMUCRU_RSTNHOLD_CON0);
-       slp_data.pmucru_rstnhold_con1 = mmio_read_32(PMUCRU_BASE +
+       pmu_slp_data.pmucru_rstnhold_con1 = mmio_read_32(PMUCRU_BASE +
                                            PMUCRU_RSTNHOLD_CON1);
        rstnhold_cofig0 = BIT_WITH_WMSK(PRESETN_NOC_PMU_HOLD) |
                          BIT_WITH_WMSK(PRESETN_INTMEM_PMU_HOLD) |
@@ -257,12 +260,33 @@ void set_pmu_rsthold(void)
        mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1, rstnhold_cofig1);
 }
 
-void restore_pmu_rsthold(void)
+void pmu_sgrf_rst_hld(void)
+{
+       mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+                     CRU_PMU_SGRF_RST_HOLD);
+}
+
+/*
+ * When system reset in running state, we want the cpus to be reboot
+ * from maskrom (system reboot),
+ * the pmusgrf reset-hold bits needs to be released.
+ * When system wake up from system deep suspend, some soc will be reset
+ * when waked up,
+ * we want the bootcpu to be reboot from pmusram,
+ * the pmusgrf reset-hold bits needs to be held.
+ */
+__pmusramfunc void pmu_sgrf_rst_hld_release(void)
+{
+       mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+                     CRU_PMU_SGRF_RST_RLS);
+}
+
+__pmusramfunc void restore_pmu_rsthold(void)
 {
        mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON0,
-                     slp_data.pmucru_rstnhold_con0 | REG_SOC_WMSK);
+                     pmu_slp_data.pmucru_rstnhold_con0 | REG_SOC_WMSK);
        mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1,
-                     slp_data.pmucru_rstnhold_con1 | REG_SOC_WMSK);
+                     pmu_slp_data.pmucru_rstnhold_con1 | REG_SOC_WMSK);
 }
 
 /**
index 6100d95581933e5128ce369cf403d0b266e4ab1a..bc4193392ebd3fd356c007894378f233529373ea 100644 (file)
@@ -134,6 +134,9 @@ struct deepsleep_data_s {
        uint32_t plls_con[END_PLL_ID][PLL_CON_COUNT];
        uint32_t cru_gate_con[CRU_GATE_COUNT];
        uint32_t pmucru_gate_con[PMUCRU_GATE_COUNT];
+};
+
+struct pmu_sleep_data {
        uint32_t pmucru_rstnhold_con0;
        uint32_t pmucru_rstnhold_con1;
 };
@@ -263,27 +266,6 @@ struct deepsleep_data_s {
 #define PMUCRU_GATEDIS_CON0 0x0130
 #define PMUCRU_SOFTRST_CON(n)   (PMUCRU_SOFTRST_CON0 + (n) * 4)
 
-/*
- * When system reset in running state, we want the cpus to be reboot
- * from maskrom (system reboot),
- * the pmusgrf reset-hold bits needs to be released.
- * When system wake up from system deep suspend, some soc will be reset
- * when waked up,
- * we want the bootcpu to be reboot from pmusram,
- * the pmusgrf reset-hold bits needs to be held.
- */
-static inline void pmu_sgrf_rst_hld_release(void)
-{
-       mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
-                     CRU_PMU_SGRF_RST_RLS);
-}
-
-static inline void pmu_sgrf_rst_hld(void)
-{
-       mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
-                     CRU_PMU_SGRF_RST_HOLD);
-}
-
 /* export related and operating SoC APIs */
 void __dead2 soc_global_soft_reset(void);
 void disable_dvfs_plls(void);
@@ -296,5 +278,7 @@ void clk_gate_con_save(void);
 void clk_gate_con_disable(void);
 void clk_gate_con_restore(void);
 void set_pmu_rsthold(void);
-void restore_pmu_rsthold(void);
+void pmu_sgrf_rst_hld(void);
+__pmusramfunc void pmu_sgrf_rst_hld_release(void);
+__pmusramfunc void restore_pmu_rsthold(void);
 #endif /* __SOC_H__ */